package cn.abellflower.utils;

import org.springframework.beans.BeanUtils;
import org.springframework.cglib.beans.BeanGenerator;
import org.springframework.cglib.beans.BeanMap;

import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author gbzdyf@126.com
 * @Create: 2019/7/3 18:47
 */
public class DynamicBeanUtil {
    private DynamicBeanUtil() {
    }

    public static Object plusProperties(Object target, Map<String, Object> propertiesValue) {
        Map<String, Class> propertiesClass = propertiesValue.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, (entry) -> {
            return entry.getValue().getClass();
        }));
        Object result = generateBean(target, propertiesClass);
        BeanMap beanMap = BeanMap.create(result);
        beanMap.putAll(propertiesValue);
        return result;
    }

    public static Object plusProperty(Object target, String propertyName, Object propertyValue) {
        return plusProperties(target, Collections.singletonMap(propertyName, propertyValue));
    }

    private static Object generateBean(Object target, Map<String, Class> propertyMap) {
        Optional<Boolean> propertiesNameCheck = propertyMap.keySet().stream().map((key) -> {
            return key != null && key.matches("[a-z][a-zA-Z0-9_$]*");
        }).reduce((b1, b2) -> {
            return b1 && b2;
        });
        if (propertiesNameCheck.isPresent() && !(Boolean)propertiesNameCheck.get()) {
            throw new IllegalArgumentException("属性名命名不规范,请检查属性名称!");
        } else {
            BeanGenerator beanGenerator = new BeanGenerator();
            beanGenerator.setSuperclass(target.getClass());
            propertyMap.forEach(beanGenerator::addProperty);
            Object result = beanGenerator.create();
            BeanUtils.copyProperties(target, result);
            return result;
        }
    }
}
